home *** CD-ROM | disk | FTP | other *** search
/ LiquidLibrary 2005 February / LiquidLibrary 2005 February - Disc 1.iso / pc / Portfolio Browser / Filters / PDF / LIB / gs_cmap.ps < prev    next >
Text File  |  2003-01-03  |  14KB  |  444 lines

  1. %    Copyright (C) 1995, 2000 Aladdin Enterprises.  All rights reserved.
  2. % This software is licensed to a single customer by Artifex Software Inc.
  3. % under the terms of a specific OEM agreement.
  4.  
  5. % $RCSfile$ $Revision$
  6. % ProcSet for implementing CMap resources.
  7. % When this is run, systemdict is still writable.
  8.  
  9. % NOTE: Rearranged fonts are not implemented yet.
  10.  
  11. % ---------------- Public operators ---------------- %
  12.  
  13. /.rewriteTempMapsNotDef {
  14.   DEBUG { (rewriting TempMapsNotDef\n) print flush } if
  15.   .TempMaps 2 get
  16.   dup length 0 gt {
  17.     0 get
  18.     DEBUG { (...original...\n) print flush } if
  19.     1 5 2 index length 1 sub {
  20.       { 1 index exch get 2 3 put } stopped
  21.       { DEBUG { (cannot rewrite\n) print flush } if }
  22.       { DEBUG { (rewrite\n) print flush } if } ifelse
  23.     } for
  24.   } if
  25.   pop
  26.   DEBUG { (...FINISHED...\n) print } if
  27. } bind def
  28.  
  29. % composefont doesn't appear in CMap files -- it's documented in
  30. % the "PostScript Language Reference Manual Supplement".
  31. /composefont {        % <name> <cmap|cmapname> <fonts> composefont <font>
  32.   10 dict begin
  33.     /CMap 2 index dup type /dicttype ne { /CMap findresource } if def
  34.     /FDepVector 1 index cvlit def    % temporarily
  35.     /Encoding [ 0 1 FDepVector length 1 sub { } for ] def
  36.     /FDepVector [ 0 1 FDepVector length 1 sub {
  37.         % Stack: name cmap[name] fonts /FDepVector [ fonts... i
  38.       FDepVector 1 index get
  39.       dup type /dicttype ne {
  40.     dup /CIDFont resourcestatus {
  41.       pop pop /CIDFont
  42.     } {
  43.       /Font
  44.     } ifelse findresource
  45.       } if
  46.       exch CMap /FontMatrices get dup length 2 index gt {
  47.     exch get dup null eq { pop } { makefont } ifelse
  48.       } {
  49.     pop pop
  50.       } ifelse
  51.     } for ] readonly def
  52.     /FMapType 9 def
  53.     /FontMatrix matrix def
  54.     /FontName 3 index def
  55.     CMap /WMode .knownget { /WMode exch def } if
  56.     /FontType 0 def
  57.   pop pop currentdict end /Font defineresource
  58. } bind odef
  59.  
  60. % ---------------- CMap operators ---------------- %
  61.  
  62. 40 dict begin
  63.  
  64. % Our internal .CodeMapData structure closely mirrors the structures
  65. % defined in gxfcmap.h (q.v.).  () indicate a string, [] indicate an array,
  66. % ? indicates a Boolean, # indicates an integer, {} for grouping.
  67. %    [[(first) (last) ...]        % code space ranges
  68. %     [(prefix) (key_size,?is_range,value_type,value_size) (keys...)
  69. %       {(values...) | [value ...]} #font_index    % code mappings
  70. %      ...]
  71. %     <<same>>        % notdef mappings
  72. %    ]
  73. % FontMatrices is the array of matrices defined by begin/endusematrix.
  74. % All of the arrays and strings are read-only after they have been built.
  75. %
  76. % Note that the code in zfcmap.c that constructs the C structures from
  77. % the PostScript structures has intimate knowledge of the above format.
  78.  
  79. % ****** NOTE: The code currently only handles "well-behaved" CMaps:
  80. %    - CID values only (no bfchars), 16-bit
  81. %    - Entries (both code space and map) must be sorted
  82. %    - Only the last byte must vary in each map range, except for
  83. %    the identity mapping
  84.  
  85. % ------ Font-level operators ------ %
  86.  
  87. /begincmap {        % - begincmap -
  88.   /.CodeMapData [[] [] []] def
  89.   /FontMatrices [] def
  90.   /.FontIndex 0 def
  91.   /.TempMaps [20 dict 50 dict 50 dict] def
  92.   /CodeMap null def        % for .buildcmap
  93. } bind def
  94. /endcmap {        % - endcmap -
  95.   .rewriteTempMapsNotDef
  96.   DEBUG {
  97.     (*** defined charmap ***\n) print
  98.     .TempMaps 1 get {exch == (\t) print ==} forall
  99.     (*** undefined charmap ***\n) print
  100.     .TempMaps 2 get {exch == (\t) print ==} forall
  101.   } if
  102.   10 dict begin 0 1 2 {
  103.     /i exch def
  104.         % Append data from .TempMaps to .CodeMapData.
  105.     /t .TempMaps i get def
  106.     .CodeMapData i get length t { exch pop length add } forall
  107.     DEBUG { (requested array size ) print dup == } if
  108.     array /a exch def
  109.     a 0 .CodeMapData i get .putmore
  110.     0 1 t length 1 sub {
  111.       t exch get .putmore
  112.     } for pop pop
  113.     .CodeMapData i a put
  114.   } for end
  115.   currentdict /.TempMaps undef
  116.   /.CodeMapData .CodeMapData .endmap def
  117.   /FontMatrices FontMatrices .endmap def
  118. } bind def
  119.  
  120. /.putmore {        % <array> <i> <array2> .putmore <array> <i+len(array2)>
  121.   3 copy putinterval length add
  122. } bind def
  123.  
  124. /.endmap {        % <map> .endmap <map>
  125.   dup type /arraytype eq {
  126.     % This might be a shared read-only array inherited via usecmap.
  127.     % Don't try to update its elements if this is the case.
  128.     dup wcheck {
  129.       0 1 2 index length 1 sub {
  130.     2 copy 2 copy get .endmap put pop
  131.       } for readonly
  132.     } if
  133.   } {
  134.     dup type /stringtype eq { readonly } if
  135.   } ifelse
  136. } bind def
  137.  
  138. /.appendmap {        % -mark- <elt> ... <array#> .appendmap -
  139.   .TempMaps exch get counttomark 1 add 1 roll
  140.   ] 1 index length exch put
  141. } bind def
  142.  
  143. /begincodespacerange {    % <count> begincodespacerange -
  144.   pop mark
  145. } bind def
  146. /endcodespacerange {    % <code_lo> <code_hi> ... endcodespacerange -
  147.   0 .appendmap
  148. } bind def
  149.  
  150. /usecmap {        % <CMap_name> usecmap -
  151.   /CMap findresource dup
  152.         % Copy the top level of .CodeMapData
  153.   /.CodeMapData exch /.CodeMapData get copyarray def
  154.   /FontMatrices exch /FontMatrices get copyarray def
  155. } bind def
  156.  
  157. /usefont {        % <fontID> usefont -
  158.   /.FontIndex exch def
  159. } bind def
  160.  
  161. /beginusematrix {    % <fontID> beginusematrix -
  162.   FontMatrices wcheck not FontMatrices length 2 index le or {
  163.     FontMatrices length 1 index 1 add .max array
  164.     dup 0 FontMatrices putinterval
  165.     /FontMatrices exch def
  166.   } if
  167. } bind def
  168. /endusematrix {        % <matrix> endusematrix -
  169.   FontMatrices 3 1 roll put
  170. } bind def
  171.  
  172. % ------ Rearranged font operators ------ %
  173.  
  174. /beginrearrangedfont {    % <font_name> <font*> beginrearrangedfont -
  175.   10 dict begin
  176.   /.FontNames exch def
  177.   /.FontName exch def
  178.   begincmap
  179. } bind def
  180. /endrearrangedfont {    % - endrearrangedfont -
  181.   (REARRANGED FONTS NOT IMPLEMENTED YET.) = flush
  182.   FontName .FontNames 0 get findfont end definefont pop
  183. } bind def
  184.  
  185. % ------ Character name/code selector operators ------ %
  186.  
  187. /beginbfchar {        % <count> beginbfchar -
  188.   pop mark
  189. } bind def
  190. /endbfchar {        % <code> <to_code|charname> ... endbfchar
  191.   counttomark 2 idiv {
  192.     counttomark -2 roll        % process in correct order
  193.     .addbfchar
  194.   } repeat 1 .appendmap
  195. } bind def
  196.  
  197. /beginbfrange {        % <count> beginbfrange -
  198.   pop mark
  199. } bind def
  200. /endbfrange {        % <code_lo> <code_hi> <to_code|(charname*)> ...
  201.             %   endbfrange -
  202.   counttomark 3 idiv {
  203.     counttomark -3 roll        % process in correct order
  204.     dup type dup /arraytype eq exch /packedarraytype eq or {
  205.             % Array value, split up.
  206.       exch pop {
  207.             % Stack: code to_code|charname
  208.     1 index exch .addbfchar
  209.             % Increment the code.  As noted above, we require
  210.             % that only the last byte vary, but we still must
  211.             % mask it after incrementing, in case the last
  212.             % value was 0xff.
  213.             % Stack: code prefix params key value fontindex
  214.     6 -1 roll dup length string copy
  215.     dup dup length 1 sub 2 copy get 1 add 255 and put
  216.       } forall pop
  217.     } {
  218.             % Single value, handle directly.
  219.       .addbfrange
  220.     } ifelse
  221.   } repeat 1 .appendmap
  222. } bind def
  223.  
  224. /.addbfchar {        % <code> <to_code|charname> .addbfchar
  225.             %   <prefix> <params> <key> <value> <font_index>
  226.   1 index exch .addbfrange
  227. } bind def
  228. /.addbfrange {        % <code_lo> <code_hi> <to_code|charname>
  229.             %   .addbfrange <<same as .addbfchar>>
  230.   4 string dup 3
  231.   3 index type /nametype eq {
  232.     2 index 2 1 put
  233.     4 -1 roll 1 array astore 4 1 roll 4
  234.   } {
  235.     2 index 2 2 put
  236.     3 index length
  237.   } ifelse put
  238.             % Stack: code_lo code_hi value params
  239.   3 index 3 index eq {
  240.             % Single value.
  241.     3 -1 roll pop exch () exch
  242.   } {
  243.             % Range.
  244.     dup 0 1 put dup 1 1 put
  245.     4 2 roll
  246.     dup dup length 1 sub 0 exch getinterval 5 1 roll    % prefix
  247.             % Stack: prefix value params code_lo code_hi
  248.     2 { exch dup length 1 sub 1 getinterval } repeat concatstrings
  249.     3 -1 roll
  250.   } ifelse
  251.   .FontIndex
  252. } bind def
  253.  
  254. % ------ CID selector operators ------ %
  255.  
  256. /begincidchar {        % <count> begincidchar -
  257.   pop mark
  258. } bind def
  259. /endcidchar {        % <code> <cid> ... endcidchar -
  260.   1 .endmapchars
  261. } bind def
  262.  
  263. /begincidrange {    % <count> begincidrange -
  264.   pop mark
  265. } bind def
  266. /endcidrange {        % <code_lo> <code_hi> <cid_base> ... endcidrange -
  267.   1 .endmapranges
  268. } bind def
  269.  
  270. /.endmapchars {        % -mark- <code> <cid> ... <map#> .endmapchars -
  271.   counttomark 1 add 1 roll
  272.   counttomark 2 idiv {
  273.     counttomark -2 roll        % process in correct order
  274.         % Construct prefix, params, key, value, font_index
  275.     <00 00 00 02> ()    % params, key
  276.     3 -1 roll .endmapvalue
  277.   } repeat
  278.   counttomark 2 add -1 roll .appendmap
  279. } bind def
  280.  
  281. /.endmapranges {    % -mark- <code_lo> <code_hi> <cid_base> ... <map#>
  282.             %   .endmapranges -
  283.   counttomark 1 add 1 roll
  284.   counttomark 3 idiv {
  285.     counttomark -3 roll        % process in correct order
  286.         % Construct prefix, params, key_lo, key_hi, value, font_index
  287.     3 1 roll    % <cid_base> <code_lo> <code_hi>
  288.         %        prefix    key
  289.         % 1-byte code:    ()    .
  290.         % 1-byte range:    ()    .
  291.         % N-byte code:    .    (*)
  292.         % N-byte range:    (*)    (*)
  293.     dup 2 index eq {    % <code_lo> == <code_hi>
  294.                    % 0: prefix_len for 1-byte code
  295.                    % 1: prefix_len for N-byte code
  296.        dup length 1 eq { 0 } { 1 } ifelse
  297.     } {            % <code_lo> != <code_hi>
  298.                  % calculate prefix_len for *-byte range
  299.        dup length 1 sub % <cid_base> <code_lo> <code_hi> <code_len-1>
  300.        0        % initial value for N
  301.        {        % <cid_base> <code_lo> <code_hi> (code_len-1)  N
  302.            dup 2 index ge { exit } if % if (N >= len - 1) exit
  303.            3 index 1 index get    % N-th byte of code_lo
  304.            3 index 2 index get    % N-th byte of code_hi
  305.            eq { 1 add } { exit } ifelse
  306.        } loop
  307.        exch pop     % discard <code_len-1>
  308.     } ifelse
  309.                 % cid_base code_lo code_hi prefix_len
  310.  
  311.     % Althogh Adobe CPSI with native CID/CMap support accept
  312.     % multi-dimensional range specification in notdef & cidrange
  313.     % (and CID is calculated as relative position in multi-dimensional
  314.     % range), but older CPSI & ATM cannot handle it.
  315.     % 
  316.     % GS accepts such specification, but it's recommended to keep
  317.     % from using this feature for notdef & cidrange.
  318.     % Following is a disabler of this feature.
  319.     % -------------------------------------------------------------
  320.     % counttomark 1 add index     % get map#
  321.     % 0 ne {            % if not codespacerange
  322.     %   1 index length         % get code length
  323.     %   1 index             % get prefix length
  324.     %   sub            % calculate key length
  325.     %   1 gt {            % if (key_len > 1),
  326.     %      (.endmapranges error) = flush
  327.     %      (multi-dimensional range specification is used out of codespacerange)
  328.     %      = flush
  329.     %      (/) =only
  330.     %      CMapName CMapName length string cvs =only
  331.     %      (: <) =only
  332.     %      2 index (%stdout) (w) file exch writehexstring
  333.     %      (> <) =only
  334.     %      1 index (%stdout) (w) file exch writehexstring
  335.     %      (>\n) =only flush
  336.     %      quit
  337.     %   } if
  338.     % } if
  339.     % -------------------------------------------------------------
  340.  
  341.     1 index exch 0 exch getinterval
  342.                 % cid_base code_lo code_hi prefix
  343.     dup length 3 index length exch sub
  344.                 % cid_base code_lo code_hi prefix range_len
  345.     dup 255 gt {
  346.        (too long coderange specification for current GS\n) print stop
  347.     } if
  348.     <00 01 00 02> 4 string copy    % create initialized param
  349.     dup 0 4 -1 roll put        % put range_len into param
  350.  
  351.     % get key_hi
  352.     3 -1 roll dup length 3 index length dup 3 1 roll sub getinterval
  353.  
  354.     % get key_lo
  355.     4 -1 roll dup length 4 index length dup 3 1 roll sub getinterval
  356.  
  357.     % make "keys" (concatenated key_lo + key_hi)
  358.     exch concatstrings
  359.  
  360.     % 
  361.     4 -1 roll
  362.     .endmapvalue
  363.  
  364.         % See if we can merge with the previous value.
  365.         % The prefix, params, and font index must match.
  366.     % prefix params keys value fontindex
  367.     counttomark 5 gt { % 2 (or more) ranges (1 range = 5 item)
  368.        4 index 10 index eq    % compare prefix
  369.        4 index 10 index eq and    % compare params
  370.        1 index 7 index eq and    % compare fontindex
  371.     {
  372.           DEBUG { (merge!\n) print } if
  373.       pop 4 2 roll pop pop
  374.            % prefix params keys value fontindex keys2 value2
  375.       5 -1 roll 3 -1 roll concatstrings
  376.            % prefix params value fontindex value2 keys'
  377.       4 -1 roll 3 -1 roll concatstrings
  378.            % prefix params fontindex keys' values'
  379.       3 -1 roll
  380.     } if
  381.      } if % end of 2 (or more) ranges
  382.   } repeat
  383.   counttomark 2 add -1 roll .appendmap
  384. } bind def
  385.  
  386. /.endmapvalue {        % <cid> .endmapvalue (hi,lo) .FontIndex
  387.   2 string dup 0 3 index -8 bitshift put    % value
  388.   dup 1 4 -1 roll 255 and put
  389.   .FontIndex        % font_index
  390. } bind def
  391.  
  392. % ------ notdef operators ------ %
  393.  
  394. /beginnotdefchar {    % <count> beginnotdefchar -
  395.   pop mark
  396. } bind def
  397. /endnotdefchar {    % <code> <cid> ... endnotdefchar -
  398.   2 .endmapchars
  399. } bind def
  400.  
  401. /beginnotdefrange {    % <count> beginnotdefrange -
  402.   pop mark
  403. } bind def
  404. /endnotdefrange {    % <code_lo> <code_hi> <cid> ... endnotdefrange -
  405.   2 .endmapranges
  406. } bind def
  407.  
  408. % ---------------- Resource category definition ---------------- %
  409.  
  410. currentdict end
  411.  
  412. languagelevel exch 2 .setlanguagelevel
  413.  
  414. /CMap /Generic /Category findresource dup length dict .copydict
  415. dup /InstanceType /dicttype put
  416. dup /DefineResource {
  417.         % The AdobePS5 Windows driver emits code that attempts to
  418.         % create CMaps without the required CMapName entry.
  419.         % Work around this here.
  420.   dup /CMapName known not {
  421.     dup wcheck not {
  422.       .currentglobal exch dup wcheck .setglobal
  423.       dup length dict .copydict exch .setglobal
  424.     } if
  425.     dup gcheck 2 index gcheck not and {
  426.       exch .currentglobal exch true .setglobal
  427.       dup length string copy exch .setglobal exch
  428.     } if dup /CMapName 3 index put
  429.   } if
  430.   dup /CodeMap get null eq { .buildcmap } if
  431.   /Generic /Category findresource /DefineResource get exec
  432. } put
  433. /Category defineresource pop
  434.     % We might have loaded CID font support already.
  435. /CIDInit /ProcSet 2 copy { findresource } .internalstopped
  436.     % An interior `stopped' might have reset VM allocation to local.
  437. true .setglobal
  438.  { pop pop 3 -1 roll }
  439.  { dup length 4 index length add dict .copydict 4 -1 roll exch .copydict }
  440. ifelse exch defineresource pop
  441.  
  442. .setlanguagelevel
  443.